/**
Copyright 2011 Fan Zhang

This file is part of Joggle.

Joggle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Joggle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Joggle.  If not, see <http://www.gnu.org/licenses/>.
*/

package edu.gwu.cs.joggle;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Fan Zhang E-mail:zfwise@gwmail.gwu.edu
 * @version 1
 * @since 2011-12-20
 */
public class Dictionary {

	private Server server;
	private String name;
	
	// all words in this Dictionary
	private List<String> dictionaryWords = new ArrayList<String>();
	
	/**
	 * Create a Dictionary from the given file on the Server
	 * @param dictFile The text file containing the master word list for this Dictionary located on the Server
	 */
	public Dictionary(Server srv, String dictFile) {
		server = srv;
		name = dictFile;
		
		BufferedReader currentBuffer = null;
		try {
			currentBuffer = new BufferedReader(new FileReader(server.getDictFolderPath() + name));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
		String tempWord = "";
		try{
			while((tempWord = currentBuffer.readLine()) != null) {
				dictionaryWords.add(tempWord);
			}
			currentBuffer.close();
		} catch (IOException e) {
			e.printStackTrace();	
		}
	}
	
	/**
	 * Use binary search to match the result.
	 * @param checkWords Words sent by Client to be verified
	 * @return String A subset (possibly empty) of checkWords that were found in this Dictionary
	 */
	protected ArrayList<String> binarySearch(List<String> checkWords){
		ArrayList<String> matchedWords = new ArrayList<String>();
		
		for(int i=0; i<checkWords.size();i++){
		    int min = 0;
		    int max = dictionaryWords.size()-1;
		    int mid = 0;
		    int cmpResult = 0;

			while(max>=min){

			    // check the length of the word
			    // words smaller than 3 characters aren't allowed
			    if (checkWords.get(i).length() < 3) 
				break;
			    
			    mid = (min + max) / 2;
			    cmpResult = checkWords.get(i).compareTo(dictionaryWords.get(mid));
			    if(cmpResult==0){
				matchedWords.add(checkWords.get(i));
				break;
			    }
			    else if(max==min){
				break;
			    }
			    else if(cmpResult > 0){ 	 	
				min = mid + 1 == max ? max : mid;
			    }
			    else{
				max = mid;
			    }			
			}
		}
		return matchedWords;
	}
	/**
	 * Use binary search to update the new words
	 * @param words is the new words
	 * @return ArrayList of valid new words.
	 * It will create a temperary file to store the newest Dictionary. 
	 */
	protected List<String> addWords(List<String> words){
		ArrayList<String> addedWords = new ArrayList<String>();
		ArrayList<String> notAddedWords = new ArrayList<String>();
		
		for(int i=0; i<words.size();i++){
		    int min = 0;
		    int max = dictionaryWords.size()-1;
		    int mid = 0;
		    int cmpResult = 0;

			while(max>=min){

			    // check the length of the word
			    // words smaller than 3 characters aren't allowed
			    if (words.get(i).length() < 3) 
			    	break;
			    
			    mid = (min + max) / 2;
			    cmpResult = words.get(i).compareTo(dictionaryWords.get(mid));
			    if(cmpResult==0){
			    	notAddedWords.add(words.get(i));
			    	break;
			    }
			    else if(max==min){
			    	addedWords.add(words.get(i));
			    	if(words.get(i).compareTo(dictionaryWords.get(min))>0)
			    		dictionaryWords.add(min+1, words.get(i));
			    	else
			    		dictionaryWords.add(min, words.get(i));
			    	
			    	break;
			    }
			    else if(cmpResult > 0){ 	 	
			    	min = mid + 1 == max ? max : mid;
			    }
			    else{
			    	max = mid;
			    }			
			}
		}
		
		//update the dictionaryWords into a temp dictionary file, maybe, dictionary_v1
		
		try {
			File f2 = new File("dictionary_v1");
			FileWriter writer = new FileWriter(f2);
			for(int j =0 ; j<dictionaryWords.size();j++){
				writer.write(dictionaryWords.get(j).toString() + "\n");
			}
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			
		}
		return addedWords;
	}
	/**
	 * Use binary search to delete words
	 * @param words is the words to be deleted
	 * @return ArrayList of valid deleted words.
	 * It will create a temperary file to store the newest Dictionary. 
	 */
	protected List<String> delWords(List<String> words){
		ArrayList<String> delWords = new ArrayList<String>();
		
		for(int i=0; i<words.size();i++){
		    int min = 0;
		    int max = dictionaryWords.size()-1;
		    int mid = 0;
		    int cmpResult = 0;

			while(max>=min){

			    // check the length of the word
			    // words smaller than 3 characters aren't allowed
			    if (words.get(i).length() < 3) 
			    	break;
			    
			    mid = (min + max) / 2;
			    cmpResult = words.get(i).compareTo(dictionaryWords.get(mid));
			    if(cmpResult==0){
			    	dictionaryWords.remove(mid);
			    	delWords.add(words.get(i));
			    	break;
			    }
			    else if(max==min){
			    	break;
			    }
			    else if(cmpResult > 0){ 	 	
			    	min = mid + 1 == max ? max : mid;
			    }
			    else{
			    	max = mid;
			    }			
			}
		}
		
		//update the dictionaryWords into a temp dictionary file, maybe, dictionary_v1
		try {
			File f2 = new File("dictionary_v1");
			FileWriter writer = new FileWriter(f2);
			for(int j =0 ; j<dictionaryWords.size();j++){
				writer.write(dictionaryWords.get(j) + "\n");
			}
			writer.close();
		} catch (IOException e) {

			e.printStackTrace();
		}
		return delWords;
	}

    /**
     * Returns a string representation of the name of the dictionary
     * @return String
     */
    protected String getName() {
		return name;
	}
	
    /**
     * Returns the size of the dictionary
     * @return int
     */
	protected int getSize() {
		return dictionaryWords.size();
	}
	
	public static void main(String[] args){
	}
	
}